package com.nmdl.test2;

import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.nmdl.test2.utils.DataProcessUtil;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;


/**
 * 作者:libeibei
 * 日期：20201222
 * 类功能说明：读取指定名称遥控器的VID、PID
 */

public class TestActivity extends AppCompatActivity {

    public static String TAG = "BLE_READ";
    public static String BLE_NAME = "川流TV";
    //    public static String BLE_MAC = "FC:E8:06:00:3B:AD";
    public static String BLE_MAC = "54:6C:0E:35:78:18";
    private Context mContext;
    private BluetoothManager bluetoothManager;
    private BluetoothAdapter bluetoothAdapter;
    protected BluetoothDevice mSelectedDevice;//之前的逻辑是连接的目标蓝牙设备，现在新增从上个界面传入的扫描到的目标蓝牙设备
    private BluetoothGatt mBluetoothGatt;
    private BluetoothGattCharacteristic mVIDPIDCharacteristic;
    //已配对的设备
    Set<BluetoothDevice> pairedDevices;
    public static List<byte[]> bytes_list = null;//要发送的数据list
    //GATT service UUID
    public static final UUID RX_SERVICE_UUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID RX_CHAR_UUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID RX_CHAR_UUID_DSC = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID RX_DESC_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    public static final UUID RX_DESC_UUID_DES = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    TextView tv_vid_pid;
    TextView status_tv;
    Button send_message_btn;
    Button dis_connect_btn;
    String VID = "";
    String PID = "";

    @SuppressLint("HandlerLeak")
    Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 0x1:
                    Toast.makeText(mContext, "VID、PID读取成功", Toast.LENGTH_LONG).show();
                    tv_vid_pid.setText("VID=" + VID + " PID=" + PID);
                    break;
                default:
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mContext = TestActivity.this;
        tv_vid_pid = (TextView) findViewById(R.id.tv_vid_pid);
        status_tv = (TextView) findViewById(R.id.status_tv);
        send_message_btn = (Button) findViewById(R.id.send_message_btn);
        dis_connect_btn = (Button) findViewById(R.id.dis_connect_btn);
//        send_message_btn.setOnClickListener(view -> setSendData("222222222222111111111111333333333333"));
        send_message_btn.setOnClickListener(view -> writeData("681800002001136803203233333A33333333E6F78168E4402EDAAF261BB2DB54C6D14B333353344633331B16"));
        dis_connect_btn.setOnClickListener(view -> {
            if (mBluetoothGatt != null) mBluetoothGatt.close();
        });
        if (getIntent().getParcelableExtra("device") != null) {
            mSelectedDevice = getIntent().getParcelableExtra("device");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mSelectedDevice != null) {
            connectGatt();
            return;
        }
        //第一步，初始化各工具
        init();
        //第二步，根据名称，获取指定的蓝牙设备：mSelectedDevice
        getTargetBLEDevice();

        //第三步，声明mGattCallback，并重写回调函数,见下面step 3

        //第四步，通过上两步获取的mSelectedDevice和mGattCallback建立GATT连接
        connectGatt();

        //第五步，建立gatt连接后，会回调mGattCallback下的onConnectionStateChange()函数
        //在onConnectionStateChange()函数中调用mBluetoothGatt.discoverServices();
        //见下面step 5

        //第六步，调用mBluetoothGatt.discoverServices()后
        // 会回调mGattCallback下的onServicesDiscovered()函数
        // 在该函数下
        // 1、获取DeviceInfoService 见下面step 6-1
        // 2、通过拿到的service，获取VIDPIDCharacteristic 见下面step 6-2
        // 3、读取获取到的这个VIDPIDCharacteristic 见下面step 6-3

        //第七步，读取VIDPIDCharacteristic后
        // 会回调mGattCallback下的onCharacteristicRead()函数
        // step 7-1：在这个函数下将读取出的value值
        // step 7-2：转码即可
        //（ascii字符转ascii值，再将十进制ascii值转为十六进制字符，即为VID和PID）
    }

    //step 1
    private void init() {
        if (bluetoothManager == null)
            bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        if (bluetoothAdapter == null)
            bluetoothAdapter = bluetoothManager.getAdapter();
        pairedDevices = bluetoothAdapter.getBondedDevices();
    }

    //step 2
    private void getTargetBLEDevice() {
        if (pairedDevices != null && pairedDevices.size() > 0) {
            for (BluetoothDevice bluetoothDevice : pairedDevices) {
                String name = bluetoothDevice.getName();
                String address = bluetoothDevice.getAddress();
                Log.i(TAG, "bluetoothDevice name:" + name + "\taddress:" + address);
                if (bluetoothDevice != null && address.equalsIgnoreCase(BLE_MAC)) {
                    Log.i(TAG, "已找到指定蓝牙设备，该设备MAC=" + bluetoothDevice.getAddress());
                    mSelectedDevice = bluetoothDevice;
                    break;
                }
            }
        }
    }

    //step 4
    private void connectGatt() {
        if (mSelectedDevice != null)
            mBluetoothGatt = mSelectedDevice.connectGatt(mContext, false, mGattCallback);
        else
            Toast.makeText(mContext, "没有找到指定的蓝牙设备，无法建立GATT", Toast.LENGTH_LONG).show();
    }

    private String strings;
    private byte commond;
    private String data;
    private int count = 0;
    private byte[] backData;

    public void writeData(String data) {
        if (data.length() <= 17 * 2 && data.length() > 0) {
            strings = data;
            if (strings.length() % 2 == 1) {
                strings = "0" + strings;
            }
            commond = (byte) 0xC0;
        } else if (data.length() > 17 * 2) {
            this.data = data;
            strings = data.substring(count * 17 * 2, (count + 1) * 17 * 2);
            commond = (byte) 0x80;
        }
        writeAmmeterData(commond, DataProcessUtil.getInstance().hexStr2Bytes(strings));
    }

    private void writeAmmeterData(byte command, byte[] data) {
        byte[] value = DataProcessUtil.getInstance().makePacket1(command, data);
        sendData(value);
    }

    private void reWriteData(boolean result, boolean end) {
        Log.e(TAG, "result: result = " + result);
        Log.e(TAG, "result: end = " + end);
        if (result) {
            if (!end) {
                count++;
                if ((data.length() - 17 * 2 * count) <= 17 * 2 && (data.length() - 17 * 2 * count) > 0) {
                    strings = data.substring(count * 17 * 2, data.length());
                    if (strings.length() % 2 == 1) {
                        strings = "0" + strings;
                    }
                    commond = (byte) ((byte) 0x40 + count);
                    count = 0;
                } else if ((data.length() - 17 * 2 * count) > 17 * 2) {
                    strings = data.substring(count * 17 * 2, (count + 1) * 17 * 2);
                    commond = (byte) ((byte) 0x00 + count);
                }
                writeAmmeterData(commond, DataProcessUtil.getInstance().hexStr2Bytes(strings));
            } else {
                Log.e(TAG, "发送成功");
            }
        } else {
            writeAmmeterData(commond, DataProcessUtil.getInstance().hexStr2Bytes(strings));
        }
    }

    private void sendBack(byte[] txValue) {
        Log.e(TAG, "onReceive: " + DataProcessUtil.getInstance().bytes2HexString(txValue));
        if (txValue[0] == (byte) 0x4B) {
            //判断反向帧
            byte[] fx = new byte[1];
            fx[0] = (byte) (txValue[1] & 0x20);
            if (fx[0] == (byte) 0x20) {
                byte end = (byte) (txValue[1] & 0x40);
                boolean endState = false;
                if (end == (byte) 0x40) {
                    endState = true;
                }
                //判断返回是否正确
                byte[] st = new byte[1];
                st[0] = (byte) (txValue[1] & 0x10);
                if (st[0] == (byte) 0x00) {
                    reWriteData(true, endState);
                } else if (st[0] == (byte) 0x10) {
                    reWriteData(false, endState);
                }
            }
        }
        if (txValue[0] == (byte) 0x4A) {
            byte[] value = new byte[]{(byte) 0x4B, (byte) (txValue[1] & (byte) 0x20), (byte) 0x00};
            sendData(value);
            byte[] buffer = new byte[(int) txValue[2]];
            byte[] bufferData = new byte[0];
            if (backData != null) {
                bufferData = backData;
            }
            backData = new byte[bufferData.length + buffer.length];
            for (int i = 0; i < buffer.length; i++) {
                buffer[i] = txValue[3 + i];
            }
            System.arraycopy(bufferData, 0, backData, 0, bufferData.length);
            System.arraycopy(buffer, 0, backData, bufferData.length, buffer.length);
            byte end = (byte) (txValue[1] & 0x40);
            if (end == (byte) 0x40) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        readResult(backData);
                    }
                });
                backData = null;
            }
        }
    }

    private void readResult(byte[] data) {
        String strData = DataProcessUtil.getInstance().bytes2HexString(data);
        Log.d(TAG, strData);
        String newData = "";
        for (int i = 0; i < strData.length() / 2 - 1; i++) {
            newData = newData + strData.substring(i * 2, (i + 1) * 2) + " ";
        }
        newData = newData + strData.substring(strData.length() - 2, strData.length());
        Log.e(TAG, "new Data===" + newData);
    }

    public void setSendData(String value) {
        if (value.length() > 12) {
            bytes_list = new ArrayList<>();
            int slice_num = (int) Math.ceil((double) value.length() / (double) 12);
            int last_slice_string_length = value.length() % 12;
            last_slice_string_length = last_slice_string_length != 0 ? last_slice_string_length : 12;
            for (int i = 0; i < slice_num; i++) {
                int sub_end_length = i < slice_num - 1 ? 12 : last_slice_string_length;
                String slice_string = value.substring(i * 12, i * 12 + sub_end_length);
                Log.i(TAG, "slice_string" + i + "==" + slice_string);
                byte[] slice_bytes = HexUtil.hexStringToBytes(slice_string);
                bytes_list.add(slice_bytes);
            }
            for (int i = 0; i < bytes_list.size(); i++) {
                Log.i(TAG, "bytes_list" + i + " value:" + HexUtil.encodeHexStr(bytes_list.get(i)));
            }
            sendData(bytes_list.get(0));
            send_message_btn.setEnabled(false);
        } else {
            bytes_list = null;
        }
    }

    private void sendData(byte[] value) {
        Log.i(TAG, "sendData----------------" + HexUtil.encodeHexStr(value));
        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE_UUID);
        if (RxService == null) {
            Log.e(TAG, "RxService==null");
            mBluetoothGatt.disconnect();
            return;
        }
        BluetoothGattCharacteristic RxChar = RxService.getCharacteristic(RX_CHAR_UUID);
        if (RxChar == null) {
            Log.e(TAG, "RxChar == null");
            mBluetoothGatt.disconnect();
            return;
        }
//        RxChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
        //设置数据
        RxChar.setValue(value);
        boolean status = mBluetoothGatt.writeCharacteristic(RxChar);
        Toast.makeText(this, status ? "发送成功！" : "发送失败！", Toast.LENGTH_SHORT).show();
    }

    //step 3
    BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.i(TAG, "onConnectionStateChange newstate:" + newState + " status:" + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    Log.i(TAG, "============>GATT Connect Success！！<=============");
                    //step 5
                    mBluetoothGatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    if (mBluetoothGatt != null) {
                        mBluetoothGatt.close();
                        mBluetoothGatt = null;
                    }
                }
            }
            if (status == 133) {
                boolean isRefreshSuccess = refreshDeviceCache(mBluetoothGatt);
                if (isRefreshSuccess) mBluetoothGatt.disconnect();
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            Log.i(TAG, "onServicesDiscovered(), status = " + status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
                mBluetoothGatt = gatt;
                //step 6-1：获取DeviceInfoService
                List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService service : services) {
                    Log.d(TAG, "service.getUuid() = " + service.getUuid());
                    List<BluetoothGattCharacteristic> charas = service.getCharacteristics();
                    for (BluetoothGattCharacteristic chara : charas) {
                        Log.e(TAG, "chara.getUuid() = " + chara.getUuid());
                        List<BluetoothGattDescriptor> descriptors = chara.getDescriptors();
                        for (BluetoothGattDescriptor descriptor : descriptors) {
                            Log.i(TAG, "descriptor.getUuid() = " + descriptor.getUuid());
                        }
                    }
                }
                BluetoothGattService mDeviceInfoService = gatt.getService(RX_SERVICE_UUID);
                if (mDeviceInfoService == null) {
                    Log.i(TAG, "Device Info Service is null ,disconnect GATT...");
                    gatt.disconnect();
                    gatt.close();
                    return;
                }
                //step 6-2:获取遥控器VIDPID Characteristic
                mVIDPIDCharacteristic = mDeviceInfoService.getCharacteristic(RX_CHAR_UUID_DSC);
                //
                mBluetoothGatt.setCharacteristicNotification(mVIDPIDCharacteristic, true);
                BluetoothGattDescriptor descriptor = mVIDPIDCharacteristic.getDescriptor(RX_DESC_UUID_DES);
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                boolean isWriteDescriptor = mBluetoothGatt.writeDescriptor(descriptor);
                runOnUiThread(() -> {
                    if (isWriteDescriptor) {
                        Log.e(TAG, "==========蓝牙准备就绪===========");
                        status_tv.setText("蓝牙准备就绪");
                        status_tv.setTextColor(Color.BLUE);
                        send_message_btn.setEnabled(true);
                        Toast.makeText(mContext, "蓝牙准备就绪！", Toast.LENGTH_SHORT).show();
                    } else {
                        status_tv.setText("蓝牙错误");
                    }
                });
                //
//                if (mVIDPIDCharacteristic == null) {
//                    Log.e(TAG, "read mModelCharacteristic not found");
//                    return;
//                } else {
//                    //step 6-3:读取遥控器VIDPID特性
//                    Log.e(TAG, "step 6-3:读取遥控器VIDPID特性");
//                    mBluetoothGatt.readCharacteristic(mVIDPIDCharacteristic);
//                }
            } else {
                Log.i(TAG, "onServicesDiscovered status false");
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
//            Log.i(TAG, "onCharacteristicWrite: characteristic.getUuid()" + characteristic.getUuid().toString());
            if (status == BluetoothGatt.GATT_SUCCESS) {
            }
            Log.i(TAG, "onCharacteristicWrite: status" + status + "  value:" + HexUtil.encodeHexStr(characteristic.getValue()));
            runOnUiThread(() -> {
                if (bytes_list != null && bytes_list.size() > 0) {
                    Log.i(TAG, "bytes_list========" + bytes_list.size());
                    bytes_list.remove(0);
                    if (bytes_list.size() > 0) {
                        sendData(bytes_list.get(0));
                        Log.i(TAG, "bytes_list~~~~~~~~~" + bytes_list.size());
                    } else {
                        Toast.makeText(mContext, "发送完成！", Toast.LENGTH_LONG).show();
                        send_message_btn.setEnabled(true);
                    }
                }
            });
        }

        //设置Descriptor后回调
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
            Log.d(TAG, "onDescriptorWrite");
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "??????????? onDescriptorWrite-->" + "描述符写入操作成功，蓝牙连接成功并可以通信成功！！！" + descriptor.getUuid());
            } else {
                Log.e(TAG, "??????????? onDescriptorWrite-->" + "描述符写入操作失败，蓝牙通信失败...");
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            //todo
            Log.e(TAG, "??????????? onCharacteristicRead" + status);
            sendBack(characteristic.getValue());
            if (status == BluetoothGatt.GATT_SUCCESS) {
                String value = "";
                if (characteristic.getUuid().equals(RX_CHAR_UUID)) {
                    //step 7-1:读取出characteristic的value值
                    value = new String(characteristic.getValue()).trim().replace(" ", "");
                    Log.i(TAG, "=====>读取到 value =" + value);
                    //step 7-2:此处为ascii表字符，需转换为十进制ascii值
                    //再将十进制ascii值，转换为十六进制
                    VID = changeAsciiTo16(value.charAt(0));
                    PID = changeAsciiTo16(value.charAt(value.length() - 1));
                    //设备VID、PID读取成功，handle更新主线程界面UI
                    handler.sendEmptyMessage(0x1);

                }
            } else {
                Log.i(TAG, "onCharacteristicRead status wrong");
                if (mBluetoothGatt != null)
                    mBluetoothGatt.disconnect();
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            //todo
            Log.e(TAG, "??????????? onCharacteristicChanged:" + characteristic.getUuid().toString());
            sendBack(characteristic.getValue());
        }
    };

    private String changeAsciiTo16(char a) {
        Log.i(TAG, "change from a =" + a);
        String value = "";
        int val = (int) a;
        Log.i(TAG, "change to 10进制ASCII值 val =" + val);
        //ascii值到
        value = Integer.toHexString(val).toUpperCase();
        Log.i(TAG, "change to 16进制字符串 value =" + value);
        return value;
    }

    /**
     * 清理本地的 BluetoothGatt 的缓存，以保证在蓝牙连接设备的时候，设备的服务、特征是最新的
     */
    private boolean refreshDeviceCache(BluetoothGatt gatt) {
        Method refreshMethod = null;
        if (null != gatt) {
            try {
                for (Method methodSub : gatt.getClass().getDeclaredMethods()) {
                    if ("connect".equalsIgnoreCase(methodSub.getName())) {
                        Class<?>[] types = methodSub.getParameterTypes();
                        if (types != null && types.length > 0) {
                            if ("int".equalsIgnoreCase(types[0].getName())) {
                                refreshMethod = methodSub;
                            }
                        }
                    }
                }
                if (refreshMethod != null) {
                    refreshMethod.invoke(gatt);
                }
                Log.d(TAG, "refreshDeviceCache-->" + "清理本地的BluetoothGatt 的缓存成功");
                return true;
            } catch (Exception localException) {
                localException.printStackTrace();
            }
        }
        Log.e(TAG, "refreshDeviceCache-->" + "清理本地清理本地的BluetoothGatt缓存失败");
        return false;
    }
}